﻿using System;
using System.Collections.Generic;

namespace Pisces
{
	
	/**
	 * 事件模块
     * created by wangqiang
    **/
	public abstract class EventModule<T, TTT> : AbstractSingletonModule<T>, InterfaceEntityLiftcycle where T : class, InterfaceEntityLiftcycle
	{
		/**
		 * 事件map
		 * key:事件id, value:回调方法数组
		 */
		protected Dictionary<TTT, Delegate> eventMap;

		protected Delegate delegateCache;

		public override void onInit()
		{
			this.eventMap = new Dictionary<TTT, Delegate>();
		}

		public override void onAwake()
		{
		}

		public override void onUpdate(float deltaTime)
		{
		}

		public override void onDestroy()
		{
			foreach (KeyValuePair<TTT,Delegate> keyValuePair in eventMap)
			{
				Delegate value = eventMap[keyValuePair.Key];
				Delegate[] delegates = value.GetInvocationList();
				foreach (Delegate @delegate in delegates)
				{
					Delegate.Remove(value, @delegate);
				}
			}
			eventMap.Clear();
		}
		
		/**
		 * 注册时,预处理事件
		 */
		private void preHandleRegister(TTT eventID)
		{
			if (!this.eventMap.TryGetValue(eventID, out delegateCache))
			{
				this.eventMap[eventID] = null;
			}
			else
			{
				this.delegateCache = null;
			}
		}

		/**
		 * 注册事件回调
		 */
		public void register(TTT eventID, Action function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action)(this.eventMap[eventID]) + function;
		}
		
		public void register<T>(TTT eventID, Action<T> function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action<T>)(this.eventMap[eventID]) + function;
		}
		
		public void register<T, W>(TTT eventID, Action<T, W> function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action<T, W>)(this.eventMap[eventID]) + function;
		}
		
		public void register<T, W, S>(TTT eventID, Action<T, W, S> function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action<T, W, S>)(this.eventMap[eventID]) + function;
		}
		
		public void register<T, W, S, U>(TTT eventID, Action<T, W, S, U> function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action<T, W, S, U>)(this.eventMap[eventID]) + function;
		}
		
		public void register<T, W, S, U, V>(TTT eventID, Action<T, W, S, U, V> function)
		{
			this.preHandleRegister(eventID);
			this.eventMap[eventID] = (Action<T, W, S, U, V>)(this.eventMap[eventID]) + function;
		}

		/**
		 * 是否存在事件以及对应的处理方法
		 */
		private bool hasEventAndFunction(TTT eventID, Delegate function)
		{
			if (function == null)
			{
				return false;
			}
        			
			if (!this.eventMap.TryGetValue(eventID, out this.delegateCache))
			{
				this.delegateCache = null;
				return false;
			}
			
			this.delegateCache = null;

			return true;
		}

		/**
		 * 注销事件回调
		 */
		public void unRegister(TTT eventID, Action function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}
		
		public void unRegister<T>(TTT eventID, Action<T> function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action<T>)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}
		
		public void unRegister<T, W>(TTT eventID, Action<T, W> function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action<T, W>)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}
		
		public void unRegister<T, W, S>(TTT eventID, Action<T, W, S> function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action<T, W, S>)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}
		
		public void unRegister<T, W, S, U>(TTT eventID, Action<T, W, S, U> function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action<T, W, S, U>)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}
		
		public void unRegister<T, W, S, U, V>(TTT eventID, Action<T, W, S, U, V> function)
		{
			if (!this.hasEventAndFunction(eventID, function))
			{
				return;
			}
			
			this.eventMap[eventID] = (Action<T, W, S, U, V>)this.eventMap[eventID] - function;

			if (this.eventMap[eventID] == null)
			{
				this.eventMap.Remove(eventID);
			}
		}

		/**
		 * 触发事件
		 */
		public void trigger(TTT eventID)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action)delegateCache)();
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e.Message}\n堆栈:{e.StackTrace}");
			}
		}
		
		public void trigger<T>(TTT eventID, T t)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action<T>)delegateCache)(t);
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e.Message}\n堆栈:{e.StackTrace}");
			}
		}
		
		public void trigger<T, W>(TTT eventID, T t, W w)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action<T, W>)delegateCache)(t, w);
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e}\n堆栈:{e.StackTrace}");
			}
		}
        
		public void trigger<T, W, S>(TTT eventID, T t, W w, S s)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action<T, W, S>)delegateCache)(t, w, s);
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e.Message}\n堆栈:{e.StackTrace}");
			}
		}
		
		public void trigger<T, W, S, U>(TTT eventID, T t, W w, S s, U u)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action<T, W, S, U>)delegateCache)(t, w, s, u);
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e.Message}\n堆栈:{e.StackTrace}");
			}
		}
		
		public void trigger<T, W, S, U, V>(TTT eventID, T t, W w, S s, U u, V v)
		{
			if (!eventMap.TryGetValue(eventID, out delegateCache))
			{
				return;
			}

			try
			{
				((Action<T, W, S, U, V>)delegateCache)(t, w, s, u, v);
			}
			catch (Exception e)
			{
				PiscesLog.error($"事件:{eventID} 回调方法异常:{e.Message}\n堆栈:{e.StackTrace}");
			}
		}
		
	}
}